Virtual device drivers use new bind_evtchn_to_irqhandler() call
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Wed, 3 Aug 2005 12:51:35 +0000 (12:51 +0000)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Wed, 3 Aug 2005 12:51:35 +0000 (12:51 +0000)
instead of directly interfacing with Linux IRQ subsystem. This
allows them to be used in situations where the IRQ subsystem is
not paravirtualised.
Signed-off-by: Keir Fraser <keir@xensource.com>
13 files changed:
linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c
linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c
linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c
linux-2.6-xen-sparse/arch/xen/kernel/reboot.c
linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c
linux-2.6-xen-sparse/drivers/xen/blkback/common.h
linux-2.6-xen-sparse/drivers/xen/blkback/interface.c
linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c
linux-2.6-xen-sparse/drivers/xen/netback/common.h
linux-2.6-xen-sparse/drivers/xen/netback/netback.c
linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h
linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/irq_vectors.h
linux-2.6-xen-sparse/include/asm-xen/evtchn.h

index 87d0d07343f531a8541ef189977a3b4801557718..1b3d1c7e6f24c64e182fdd4af7c7bcb208857df6 100644 (file)
@@ -62,6 +62,8 @@
 #include <mach_wakecpu.h>
 #include <smpboot_hooks.h>
 
+#include <asm-xen/evtchn.h>
+
 /* Set if we find a B stepping CPU */
 static int __initdata smp_b_stepping;
 
@@ -1534,13 +1536,13 @@ void smp_intr_init(void)
        int cpu = smp_processor_id();
 
        per_cpu(resched_irq, cpu) =
-               bind_ipi_on_cpu_to_irq(RESCHEDULE_VECTOR);
+               bind_ipi_to_irq(RESCHEDULE_VECTOR);
        sprintf(resched_name[cpu], "resched%d", cpu);
        BUG_ON(request_irq(per_cpu(resched_irq, cpu), smp_reschedule_interrupt,
                           SA_INTERRUPT, resched_name[cpu], NULL));
 
        per_cpu(callfunc_irq, cpu) =
-               bind_ipi_on_cpu_to_irq(CALL_FUNCTION_VECTOR);
+               bind_ipi_to_irq(CALL_FUNCTION_VECTOR);
        sprintf(callfunc_name[cpu], "callfunc%d", cpu);
        BUG_ON(request_irq(per_cpu(callfunc_irq, cpu),
                           smp_call_function_interrupt,
index f64d6d1d26fbde90518b02f505114c6d6ac9408c..fe732b2809fc0bef4225ecdb2ee539b5492ded50 100644 (file)
@@ -70,6 +70,8 @@
 
 #include "io_ports.h"
 
+#include <asm-xen/evtchn.h>
+
 extern spinlock_t i8259A_lock;
 int pit_latch_buggy;              /* extern */
 
index 2a15fd59654c31fef2579d7023f90eee5868c68f..005caf3a21f5dd080f5d11ecdeb8115f6a443f96 100644 (file)
@@ -229,12 +229,13 @@ void unbind_virq_from_irq(int virq)
         if ( HYPERVISOR_event_channel_op(&op) != 0 )
             panic("Failed to unbind virtual IRQ %d\n", virq);
 
-       /* This is a slight hack.  Interdomain ports can be allocated
-          directly by userspace, and at that point they get bound by
-          Xen to vcpu 0.  We therefore need to make sure that if we
-          get an event on an event channel we don't know about vcpu 0
-          handles it.  Binding channels to vcpu 0 when closing them
-          achieves this. */
+        /*
+        * This is a slight hack. Interdomain ports can be allocated directly 
+        * by userspace, and at that point they get bound by Xen to vcpu 0. We 
+        * therefore need to make sure that if we get an event on an event 
+        * channel we don't know about vcpu 0 handles it. Binding channels to 
+        * vcpu 0 when closing them achieves this.
+         */
        bind_evtchn_to_cpu(evtchn, 0);
         evtchn_to_irq[evtchn] = -1;
         irq_to_evtchn[irq]    = -1;
@@ -244,7 +245,7 @@ void unbind_virq_from_irq(int virq)
     spin_unlock(&irq_mapping_update_lock);
 }
 
-int bind_ipi_on_cpu_to_irq(int ipi)
+int bind_ipi_to_irq(int ipi)
 {
     evtchn_op_t op;
     int evtchn, irq;
@@ -306,7 +307,7 @@ void unbind_ipi_from_irq(int ipi)
     spin_unlock(&irq_mapping_update_lock);
 }
 
-int bind_evtchn_to_irq(int evtchn)
+int bind_evtchn_to_irq(unsigned int evtchn)
 {
     int irq;
 
@@ -326,7 +327,7 @@ int bind_evtchn_to_irq(int evtchn)
     return irq;
 }
 
-void unbind_evtchn_from_irq(int evtchn)
+void unbind_evtchn_from_irq(unsigned int evtchn)
 {
     int irq = evtchn_to_irq[evtchn];
 
@@ -341,6 +342,33 @@ void unbind_evtchn_from_irq(int evtchn)
     spin_unlock(&irq_mapping_update_lock);
 }
 
+int bind_evtchn_to_irqhandler(
+    unsigned int evtchn,
+    irqreturn_t (*handler)(int, void *, struct pt_regs *),
+    unsigned long irqflags,
+    const char *devname,
+    void *dev_id)
+{
+    unsigned int irq;
+    int retval;
+
+    BUG_ON((irqflags & ~SA_SAMPLE_RANDOM) != 0);
+
+    irq = bind_evtchn_to_irq(evtchn);
+    retval = request_irq(irq, handler, irqflags, devname, dev_id);
+    if ( retval != 0 )
+        unbind_evtchn_from_irq(evtchn);
+
+    return retval;
+}
+
+void unbind_evtchn_from_irqhandler(unsigned int evtchn, void *dev_id)
+{
+    unsigned int irq = evtchn_to_irq[evtchn];
+    free_irq(irq, dev_id);
+    unbind_evtchn_from_irq(evtchn);
+}
+
 static void do_nothing_function(void *ign)
 {
 }
@@ -358,34 +386,33 @@ static void rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
        return;
     }
 
-    /* Tell Xen to send future instances of this interrupt to the
-       other vcpu */
+    /* Tell Xen to send future instances of this interrupt to other vcpu. */
     op.cmd = EVTCHNOP_bind_vcpu;
     op.u.bind_vcpu.port = evtchn;
     op.u.bind_vcpu.vcpu = tcpu;
 
-    /* If this fails, it usually just indicates that we're dealing
-       with a virq or IPI channel, which don't actually need to be
-       rebound.  Ignore it, but don't do the xenlinux-level rebind
-       in that case. */
+    /*
+     * If this fails, it usually just indicates that we're dealing with a virq 
+     * or IPI channel, which don't actually need to be rebound. Ignore it, 
+     * but don't do the xenlinux-level rebind in that case.
+     */
     if (HYPERVISOR_event_channel_op(&op) >= 0)
        bind_evtchn_to_cpu(evtchn, tcpu);
 
     spin_unlock(&irq_mapping_update_lock);
 
-    /* Now send the new target processor a NOP IPI.  When this
-       returns, it will check for any pending interrupts, and so
-       service any that got delivered to the wrong processor by
-       mistake. */
-    /* XXX: The only time this is called with interrupts disabled is
-       from the hotplug/hotunplug path.  In that case, all cpus are
-       stopped with interrupts disabled, and the missed interrupts
-       will be picked up when they start again.  This is kind of a
-       hack.
-    */
-    if (!irqs_disabled()) {
+    /*
+     * Now send the new target processor a NOP IPI. When this returns, it 
+     * will check for any pending interrupts, and so service any that got 
+     * delivered to the wrong processor by mistake.
+     * 
+     * XXX: The only time this is called with interrupts disabled is from the 
+     * hotplug/hotunplug path. In that case, all cpus are stopped with 
+     * interrupts disabled, and the missed interrupts will be picked up when 
+     * they start again. This is kind of a hack.
+     */
+    if (!irqs_disabled())
        smp_call_function(do_nothing_function, NULL, 0, 0);
-    }
 }
 
 
index 5c99babb2679509a2cb788eca598146975f0d502..e56e1edcee6732e8d04638f20fc0ff97540909d2 100644 (file)
@@ -12,6 +12,7 @@ static int errno;
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
 #include <asm-xen/ctrl_if.h>
+#include <asm-xen/evtchn.h>
 #include <asm-xen/hypervisor.h>
 #include <asm-xen/xen-public/dom0_ops.h>
 #include <asm-xen/linux-public/suspend.h>
index 1fbead78c4e0214727819607beb2488ce3426a02..50c609fafb660b2b8ba52895bf82c364e029663f 100644 (file)
@@ -12,7 +12,6 @@
  */
 
 #include "common.h"
-#include <asm-xen/evtchn.h>
 #ifdef CONFIG_XEN_BLKDEV_GRANT
 #include <asm-xen/xen-public/grant_table.h>
 #endif
index f3331a06a9767c3bbb1289063f6bd84e5169a05c..bc36983ce7372e67a94fc90297030503a3a1f0ab 100644 (file)
@@ -13,6 +13,7 @@
 #include <asm/setup.h>
 #include <asm/pgalloc.h>
 #include <asm-xen/ctrl_if.h>
+#include <asm-xen/evtchn.h>
 #include <asm-xen/hypervisor.h>
 #include <asm-xen/xen-public/io/blkif.h>
 #include <asm-xen/xen-public/io/ring.h>
@@ -42,7 +43,6 @@ typedef struct blkif_st {
     /* Physical parameters of the comms window. */
     unsigned long     shmem_frame;
     unsigned int      evtchn;
-    int               irq;
     /* Comms information. */
     blkif_back_ring_t blk_ring;
     /* VBDs attached to this interface. */
index aaa976c5579966392551cdad34b5bb85225710f7..accfd779631d4a5f337fcea4efad72ea273b7024 100644 (file)
@@ -38,7 +38,7 @@ static void __blkif_disconnect_complete(void *arg)
      * may be outstanding requests at the disc whose asynchronous responses
      * must still be notified to the remote driver.
      */
-    unbind_evtchn_from_irq(blkif->evtchn);
+    unbind_evtchn_from_irqhandler(blkif->evtchn, blkif);
 
 #ifdef CONFIG_XEN_BLKDEV_GRANT
     {
@@ -247,12 +247,12 @@ void blkif_connect(blkif_be_connect_t *connect)
     BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE);
     
     blkif->evtchn        = evtchn;
-    blkif->irq           = bind_evtchn_to_irq(evtchn);
     blkif->shmem_frame   = shmem_frame;
     blkif->status        = CONNECTED;
     blkif_get(blkif);
 
-    request_irq(blkif->irq, blkif_be_int, 0, "blkif-backend", blkif);
+    bind_evtchn_to_irqhandler(
+        blkif->evtchn, blkif_be_int, 0, "blkif-backend", blkif);
 
     connect->status = BLKIF_BE_STATUS_OKAY;
 }
@@ -277,7 +277,6 @@ int blkif_disconnect(blkif_be_disconnect_t *disconnect, u8 rsp_id)
         blkif->status = DISCONNECTING;
         blkif->disconnect_rspid = rsp_id;
         wmb(); /* Let other CPUs see the status change. */
-        free_irq(blkif->irq, blkif);
         blkif_deschedule(blkif);
         blkif_put(blkif);
         return 0; /* Caller should not send response message. */
index 04c0f0fdbfe4c05020a2dc5dd86f5c717d3ef6f8..cc57bb49150604064a97c8343b17fc53a1082923 100644 (file)
@@ -78,7 +78,6 @@ static void vbd_update(void){};
 static int blkif_handle = 0;
 static unsigned int blkif_state = BLKIF_STATE_CLOSED;
 static unsigned int blkif_evtchn = 0;
-static unsigned int blkif_irq = 0;
 
 static int blkif_control_rsp_valid;
 static blkif_response_t blkif_control_rsp;
@@ -1159,10 +1158,7 @@ static void blkif_free(void)
         free_page((unsigned long)blk_ring.sring);
         blk_ring.sring = NULL;
     }
-    free_irq(blkif_irq, NULL);
-    blkif_irq = 0;
-    
-    unbind_evtchn_from_irq(blkif_evtchn);
+    unbind_evtchn_from_irqhandler(blkif_evtchn, NULL);
     blkif_evtchn = 0;
 }
 
@@ -1266,12 +1262,12 @@ static void blkif_connect(blkif_fe_interface_status_t *status)
     int err = 0;
 
     blkif_evtchn = status->evtchn;
-    blkif_irq    = bind_evtchn_to_irq(blkif_evtchn);
 
-    err = request_irq(blkif_irq, blkif_int, SA_SAMPLE_RANDOM, "blkif", NULL);
-    if ( err )
+    err = bind_evtchn_to_irqhandler(
+        blkif_evtchn, blkif_int, SA_SAMPLE_RANDOM, "blkif", NULL);
+    if ( err != 0 )
     {
-        WPRINTK("request_irq failed (err=%d)\n", err);
+        WPRINTK("bind_evtchn_to_irqhandler failed (err=%d)\n", err);
         return;
     }
 
index aa780027e25e0127de231071e6eff4e918e9a04e..8a4eaadc285f4ddf1ddf1aa8e9aedffd908778bb 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <asm-xen/ctrl_if.h>
+#include <asm-xen/evtchn.h>
 #include <asm-xen/xen-public/io/netif.h>
 #include <asm/io.h>
 #include <asm/pgalloc.h>
index b85d75ac13c7b21e4df7b363240cbaf2f295ddfc..edc6c67d1fbd35348d45961ad22cd64f3f48ca28 100644 (file)
@@ -12,7 +12,6 @@
 
 #include "common.h"
 #include <asm-xen/balloon.h>
-#include <asm-xen/evtchn.h>
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
 #include <linux/delay.h>
index 59be3829eec4f9ededa5a708e9aadd0cae842766..f4cde5f102229a03e3abfaa0e9300be13e19c68c 100644 (file)
 #define dynirq_to_irq(_x)      ((_x) + DYNIRQ_BASE)
 #define irq_to_dynirq(_x)      ((_x) - DYNIRQ_BASE)
 
-#ifndef __ASSEMBLY__
-/* Dynamic binding of event channels and VIRQ sources to Linux IRQ space. */
-extern int  bind_virq_to_irq(int virq);
-extern void unbind_virq_from_irq(int virq);
-extern int  bind_ipi_to_irq(int ipi);
-extern int  bind_ipi_on_cpu_to_irq(int ipi);
-extern void unbind_ipi_from_irq(int ipi);
-extern int  bind_evtchn_to_irq(int evtchn);
-extern void unbind_evtchn_from_irq(int evtchn);
-
-extern void irq_suspend(void);
-extern void irq_resume(void);
-#endif /* __ASSEMBLY__ */
-
 #endif /* _ASM_IRQ_VECTORS_H */
index 4d3023498c9402b41e43f2ef4d516f94e43ff260..690560c8236074ad490b7e8736c91ae2c6859bc8 100644 (file)
 #define dynirq_to_irq(_x)      ((_x) + DYNIRQ_BASE)
 #define irq_to_dynirq(_x)      ((_x) - DYNIRQ_BASE)
 
-#ifndef __ASSEMBLY__
-/* Dynamic binding of event channels and VIRQ sources to Linux IRQ space. */
-extern int  bind_virq_to_irq(int virq);
-extern void unbind_virq_from_irq(int virq);
-extern int  bind_ipi_to_irq(int ipi);
-extern int  bind_ipi_on_cpu_to_irq(int ipi);
-extern void unbind_ipi_from_irq(int ipi);
-extern int  bind_evtchn_to_irq(int evtchn);
-extern void unbind_evtchn_from_irq(int evtchn);
-
-extern void irq_suspend(void);
-extern void irq_resume(void);
-#endif /* __ASSEMBLY__ */
-
 #endif /* _ASM_IRQ_VECTORS_H */
index a1801c19810dfd0732d8bbd4700122d91bac1e28..e38e6822c8eadfd399e3dda5fe33219a00c38499 100644 (file)
@@ -32,6 +32,7 @@
 #define __ASM_EVTCHN_H__
 
 #include <linux/config.h>
+#include <linux/interrupt.h>
 #include <asm-xen/hypervisor.h>
 #include <asm/ptrace.h>
 #include <asm-xen/synch_bitops.h>
  * LOW-LEVEL DEFINITIONS
  */
 
+/* Dynamically bind a VIRQ source to Linux IRQ space. */
+extern int  bind_virq_to_irq(int virq);
+extern void unbind_virq_from_irq(int virq);
+
+/* Dynamically bind an IPI source to Linux IRQ space. */
+extern int  bind_ipi_to_irq(int ipi);
+extern void unbind_ipi_from_irq(int ipi);
+
+/* Dynamically bind an event-channel port to Linux IRQ space. */
+extern int  bind_evtchn_to_irq(unsigned int evtchn);
+extern void unbind_evtchn_from_irq(unsigned int evtchn);
+
+/*
+ * Dynamically bind an event-channel port to an IRQ-like callback handler.
+ * On some platforms this may not be implemented via the Linux IRQ subsystem.
+ * You *cannot* trust the irq argument passed to the callback handler.
+ */
+extern int  bind_evtchn_to_irqhandler(
+    unsigned int evtchn,
+    irqreturn_t (*handler)(int, void *, struct pt_regs *),
+    unsigned long irqflags,
+    const char *devname,
+    void *dev_id);
+extern void unbind_evtchn_from_irqhandler(unsigned int evtchn, void *dev_id);
+
+extern void irq_suspend(void);
+extern void irq_resume(void);
+
 /* Entry point for notifications into Linux subsystems. */
 asmlinkage void evtchn_do_upcall(struct pt_regs *regs);